package com.usefullc.crawler.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.usefullc.common.enums.YesNoEnum;
import com.usefullc.common.exception.BizException;
import com.usefullc.common.util.BeanUtils;
import com.usefullc.crawler.component.DatabaseComponent;
import com.usefullc.crawler.domain.ActiveInstance;
import com.usefullc.crawler.domain.ActiveMainInstance;
import com.usefullc.crawler.domain.ActiveProcess;
import com.usefullc.crawler.domain.OutputTemplate;
import com.usefullc.crawler.enums.ActiveInstanceStatusEnum;
import com.usefullc.crawler.enums.ProcessStatusEnum;
import com.usefullc.crawler.mapper.ActiveMainInstanceMapper;
import com.usefullc.crawler.query.ActiveInstanceQuery;
import com.usefullc.crawler.query.ActiveMainInstanceQuery;
import com.usefullc.crawler.query.ActiveProcessQuery;
import com.usefullc.crawler.selenium.CrawlerWebDriver;
import com.usefullc.crawler.selenium.CrawlerWebDriverBuilder3;
import com.usefullc.crawler.selenium.CrawlerWebDriverParam;
import com.usefullc.crawler.vo.ActiveMainInstanceVo;
import com.usefullc.crawler.vo.OutputContext;
import com.usefullc.system.entity.Pager;
import com.usefullc.system.service.AbstractBizService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.*;

/**
 * 爬虫主活动实例服务类
 *
 * @author: 星空
 * @date: 2022-12-14
 */
@Service
public class ActiveMainInstanceService extends AbstractBizService<ActiveMainInstanceMapper, ActiveMainInstance, ActiveMainInstanceQuery> {


    @Autowired
    private ActiveProcessService activeProcessService;

    @Autowired
    private ActiveInstanceService activeInstanceService;

    @Autowired
    private OutputTemplateService outputTemplateService;

    @Autowired
    private DatabaseComponent databaseComponent;

    @Autowired
    private CrawlerWebDriverBuilder3 crawlerWebDriverBuilder;

    @Override
    protected QueryWrapper<ActiveMainInstance> getQueryWrapper(ActiveMainInstanceQuery query) {
        QueryWrapper<ActiveMainInstance> queryWrapper = super.getQueryWrapper(query);
        return queryWrapper;
    }

    public Pager<ActiveMainInstanceVo> findVoByPage(ActiveMainInstanceQuery query) {
        Pager<ActiveMainInstance> page = this.findByPage(query);
        Pager<ActiveMainInstanceVo> newPage = new Pager<>(page);
        List<ActiveMainInstance> dataList = page.getDataList();
        List<ActiveMainInstanceVo> newDataList = new ArrayList<>();
        newPage.setDataList(newDataList);
        for (ActiveMainInstance activeMainInstance : dataList) {
            ActiveMainInstanceVo activeMainInstanceVo = BeanUtils.beanCopy(activeMainInstance, ActiveMainInstanceVo.class);
            newDataList.add(activeMainInstanceVo);
        }
        return newPage;
    }

    public int decrSuccessNum(Long id, int num) {
        return this.getBaseMapper().decrSuccessNum(id, num);
    }

    public int updateToFail(Long id) {
        return this.getBaseMapper().updateToFail(id);
    }

    @Transactional
    public void statActiveMainInstance() {
        //通过定时任务去汇总，这里导致总数有差异
        //获取正在运行中的流程活动列表
        ActiveProcessQuery activeProcessQuery = new ActiveProcessQuery();
        activeProcessQuery.setStatus(ProcessStatusEnum.RUNNING.getCode());
        List<ActiveProcess> dataList = activeProcessService.findAll(activeProcessQuery);
        logger.info("get running process instance size={}",dataList.size());
        for (ActiveProcess activeProcess : dataList) {
            //获取最近运行中的主活动
            ActiveMainInstanceQuery query = new ActiveMainInstanceQuery();
            query.setActiveProcessId(activeProcess.getId());
            query.setStatusList(Arrays.asList(new Integer[]{ProcessStatusEnum.RUNNING.getCode()}));
            List<ActiveMainInstance> activeMainInstanceList = this.findAll(query);
            if (CollectionUtils.isEmpty(activeMainInstanceList) || activeMainInstanceList.size() > 1) {
                continue;
            }

            ActiveMainInstance activeMainInstance = activeMainInstanceList.get(0);
            Long activeMainInstanceId = activeMainInstance.getId();
            ActiveInstanceQuery activeInstanceQuery = new ActiveInstanceQuery();
            activeInstanceQuery.setActiveMainInstanceId(activeMainInstanceId);
            activeInstanceQuery.setStatus(ActiveInstanceStatusEnum.SUCCESS.getCode());
            long successNum = activeInstanceService.count(activeInstanceQuery);

            activeInstanceQuery.setStatus(ActiveInstanceStatusEnum.FAILED.getCode());
            long failedNum = activeInstanceService.count(activeInstanceQuery);

            activeMainInstance.setSuccessNum((int)successNum);
            activeMainInstance.setFailNum((int)failedNum);
            this.save(activeMainInstance);  //保存

//            if(successNum == activeMainInstance.getTotalNum()){  //全部成功
            if((successNum + failedNum)  == activeMainInstance.getTotalNum()){  //成功+失败（允许有失败）
                //仅执行一次
                int result = this.getBaseMapper().updateToSuccess(activeMainInstanceId);
                if (result > 0) {
                    //如果成功，开始下一个活动
                    activeProcessService.startActive(activeMainInstance.getActiveProcessId(), activeMainInstance.getActiveId(), true);
                }
            }
//            for (ActiveMainInstance activeMainInstance : activeMainInstanceList) {
//
////                else if(successNum + failedNum == activeMainInstance.getTotalNum()){  //仅执行一次
////                    int result = this.getBaseMapper().updateToFail(activeMainInstanceId);
////                }
//            }
        }

    }


    public void output(Long mainActiveInstanceId, Long outputTemplateId) {
        //获取所有已经执行完成的活动实例列表
        ActiveInstanceQuery activeInstanceQuery = new ActiveInstanceQuery();
        activeInstanceQuery.setActiveMainInstanceId(mainActiveInstanceId);
//        activeInstanceQuery.setStatus(YesNoEnum.YES.getCode());
        List<ActiveInstance> activeInstanceList = activeInstanceService.findAllAnalyseDataList(activeInstanceQuery);
        if (CollectionUtils.isEmpty(activeInstanceList)) {
            return;
        }
        OutputTemplate outputTemplate = outputTemplateService.findById(outputTemplateId);
//        Map<String, String> headerMap = new HashMap<>();
//        String header = outputTemplate.getHeader();
//        if (StringUtils.isNotEmpty(header)) {
//            headerMap = JsonUtil.json2Bean(header,Map.class);
//        }

        //获取webdriver
        CrawlerWebDriver crawlerWebDriver = crawlerWebDriverBuilder.buildFirefox(new CrawlerWebDriverParam());
        try{
//            WebDriver webDriver = crawlerWebDriver.getWebDriver();
            OutputContext outputContext = new OutputContext();
            outputContext.setIndex(1);
            for (ActiveInstance activeInstance : activeInstanceList) {

                outputTemplateService.outputSingle(outputContext,activeInstance,outputTemplate,crawlerWebDriver);
//                try{
//                }catch (Exception e){
//                    if (e.getCause() instanceof SQLIntegrityConstraintViolationException){
//                        logger.error("sql error",e);
//                    }else{
//                        throw e;
//                    }
//                }
                outputContext.setIndex(outputContext.getIndex()+1);
//                //get packet
//                String script = "var dataSource = "+activeInstance.getResponseAnalyseBody()+";";
//                script += outputTemplate.getPacket();
//                Object jsResult = crawlerWebDriverBuilder.executeScript(webDriver, script);
//                String resultPacket;
//                if(jsResult instanceof Map){
//                    resultPacket = JsonUtil.bean2Json(jsResult);
//                }else{
//                    resultPacket = jsResult.toString();
//                }
//                if (outputTemplate.getType().equals(OutputTemplateTypeEnum.HTTP.getCode())) {
//                    RequestRes requestRes = new RequestRes();
//                    requestRes.setMethod(outputTemplate.getMethod());
//                    requestRes.setHeaders(headerMap);
//                    requestRes.setUrl(outputTemplate.getUrl());
//                    requestRes.setParamText(resultPacket);
//                    ResponseRes responseRes = HttpNewUtils.execute(requestRes);
//                    logger.info("activeInstanceId={},responseRes={}", activeInstance.getId(), responseRes);
//
//                } else if (outputTemplate.getType().equals(OutputTemplateTypeEnum.JDBC.getCode())) {
//                    int result = databaseComponent.send(outputTemplateId, DatabaseTypeEnum.MYSQL.getCode(), resultPacket);
//                    logger.info("activeInstanceId={},result={}", activeInstance.getId(), result);
//                }
            }

        }catch (Exception e){
            throw new BizException(e);
        }finally {
            crawlerWebDriverBuilder.closeDirect(crawlerWebDriver);
        }
    }



}
